<template>
  <div
    id="page"
    class="page"
    :style="{
      width: width + unit,
      height: height + unit,
    }"
  >
    <!-- 是否显示 视图窗格 -->
    <div class="show-view-btn" :class="isShowView?'font-color-base':'font-color-gray'">
      <span @click="doShowView">显示视图</span>
    </div>
    <!-- 内容视图 -->
    <div
      v-if="isShowView"
      class="view-box"
      id="view-box"
      :style="{
        width: width * view.scolling + unit,
        height: height * view.scolling + unit,
      }"
    >
      <div
        class="view"
        :style="{
          top: content.top * view.scolling + unit,
          left: content.left * view.scolling + unit,
          width: view.width + unit,
          height: view.height + unit,
        }"
      >
        <span
          v-for="(item, index) in content.items"
          :key="'view-item-' + index"
          :style="{
            left: item.left * view.scolling + unit,
            top: item.top * view.scolling + unit,
          }"
        >
          <p
            v-if="item.type == 'text'"
            :style="{
              fontSize: item.size * view.scolling + unit,
            }"
          >
            {{ item.data }}
          </p>
          <img
            v-if="item.type == 'img'"
            :src="item.data"
            :style="{
              width: item.size.width * view.scolling + unit,
              height: item.size.height * view.scolling + unit,
            }"
          />
        </span>
      </div>
    </div>
    <!-- 可编辑内容 -->
    <div
      id="content"
      class="content"
      :style="{
        width: content.width + unit,
        height: content.height + unit,
        top: content.top + unit,
        left: content.left + unit,
      }"
    >
      <span
        v-for="(item, index) in content.items"
        :key="'content-item-' + index"
        :class="item.selected ? 'content-item-selected' : ''"
        :style="{
          left: item.left + unit,
          top: item.top + unit,
        }"
      >
        <i class="content-item-number no-pointer">{{ index + 1 }}</i>
        <p
          v-if="item.type == 'text'"
          :id="'content-item-' + index"
          :style="{
            fontSize: item.size + unit,
          }"
        >
          {{ item.data }}
        </p>
        <img
          v-if="item.type == 'img'"
          :id="'content-item-' + index"
          :src="item.data"
          :style="{
            width: item.size.width + unit,
            height: item.size.height + unit,
          }"
        />
      </span>
    </div>
    <!-- 所有添加元素列表 -->
    <van-popup v-model:show="isShowAddItemList" position="left">
      <div id="left-list" class="left-list">
        <div class="left-list-box">
          <span
            @click="addContentItem(item, index)"
            v-for="(item, index) in elementList"
            :key="'left-list-item-' + index"
            class="left-list-item"
            >{{ item.name }}</span
          >
        </div>
      </div>
    </van-popup>
    <!-- 内容所有元素列表 -->
    <van-popup v-model:show="isShowItemsList" position="right">
      <div id="right-list" class="right-list">
        <div class="right-list-box">
          <div
            @click="selectContentItem(item, index)"
            v-for="(item, index) in content.items"
            :key="'right-list-item-' + index"
          >
            {{ index + 1
            }}<span
              :class="item.selected ? 'right-list-item-selected' : ''"
              class="right-list-item"
              >{{ item.name }}</span
            >
          </div>
        </div>
      </div>
    </van-popup>
    <div>
      <span class="add-icon" @click="isShowItemsList = true">+</span>
      <span class="show-icon" @click="isShowAddItemList = true">+</span>
    </div>
  </div>
</template>

<script>
// touch 数据结构 标准化 （初始化）
const initTouchObj = {
  num: 0,
  start: {
    x: 0,
    y: 0,
  },
};
import imgData from "../assets/images/data1.jpg";
import { Popup } from "vant";
export default {
  components: {
    [Popup.name]: Popup,
  },
  props: {
    unit: {
      type: String,
      default: "px"
    },
    subWidth: {
      type: Number,
      default: 0,
    },
    subHeight: {
      type: Number,
      default: 0,
    },
    contentWidth: {
      type: Number,
      default: 100,
    },
    contentHeight: {
      type: Number,
      default: 100,
    },
    elements: {
      type: Array,
      default: []
    }
  },
  data() {
    return {
      width: 0,
      height: 0,
      config: {
        windowsX: 0,
        windowsY: 0,
        speedX: 1,
        speedY: 1,
        itemSpeedX: 1,
        itemSpeedY: 1,
        // color: "#ff6600",
      },
      // 所有 能添加 的 元素
      elementList: [
        {
          type: "img",
          data: imgData,
          name: "guluimg",
          left: 0,
          top: 0,
          size: {
            width: 200,
            height: 200,
          },
          selected: false,
        },
        {
          type: "text",
          data: "gulu1",
          name: "gulu1",
          left: 0,
          top: 0,
          size: 26,
          selected: false,
        },
      ],
      // 所有 能添加 的 元素 end
      content: {
        width: "",
        height: "",
        top: 0,
        left: 0,
        items: [],
      },
      view: {
        width: 0,
        height: 0,
        scolling: 0.1,
      },
      touchData: {
        // 0 是 content 的接触数据
        content: [
          {
            num: 0,
            start: {
              x: 0,
              y: 0,
            },
          },
        ],
        items: [],
      },
      isShowItemsList: false,
      isShowAddItemList: false,
      isShowView: false, //是否显示视图
    };
  },
  watch: {},
  computed: {},
  // created() {},
  mounted() {
    // console.log(document.body.offsetHeight);
    this.width = document.body.offsetWidth - Number.parseInt(this.subWidth);
    this.height = document.body.offsetHeight - Number.parseInt(this.subHeight);
    // if(this.subWidth) {

    // }

    // 内容框 的 移动 速度
    this.config.windowsX =
      window.innerWidth ||
      document.documentElement.clientWidth ||
      document.body.clientWidth;
    this.config.windowsY =
      window.innerHeight ||
      document.documentElement.clientHeight ||
      document.body.clientHeight;
    // this.config.speedX = 100 / this.config.windowsX;
    // this.config.speedY = 100 / this.config.windowsY;
    // 内容框内元素 的 移动 速度
    this.content.width = Number.parseInt(this.contentWidth);
    this.content.height = Number.parseInt(this.contentHeight);
    // this.config.itemSpeedX = 100 / this.content.width;
    // this.config.itemSpeedY = 100 / this.content.height;
    // 视图宽高
    this.view.width = this.content.width * this.view.scolling;
    this.view.height = this.content.height * this.view.scolling;
    this.setEventListener(
      document.getElementById("content"),
      this.content,
      1,
      true
    );
  },
  methods: {
    // 检查输入 参数
    // checkProps() {
    //   if (this.elementList)
    // },
    doShowView() {
      this.isShowView = !this.isShowView;
      if (this.isShowView) {
        // this.setEventListener(document.getElementById('view-box'), );
      }else {
      }
    },
    // 添加元素到内容面板
    addContentItem(item) {
      const item2 = JSON.parse(JSON.stringify(item));
      item2.index = JSON.parse(JSON.stringify(this.content.items.length));
      this.content.items = this.content.items.concat(item2);
      this.isShowAddItemList = false;
      this.selectContentItem(this.content.items[item2.index], item2.index);
    },
    // 选择内容面板元素
    selectContentItem(item, index) {
      // 设置选中样式
      item.selected = !item.selected;
      // 为元素添加 监听
      this.$nextTick(() => {
        const dom = document.getElementById("content-item-" + index);
        if (item.selected) {
          this.setEventListener(
            document.getElementById("content-item-" + index),
            item,
            1
          );
        } else {
          // 取消 所有事件
          this.clearEventListener(dom, item.eventListenerFunsList);
        }
      });
    },
    // 清除内容面板 元素
    clearContentItem(item, index) {
      if (!item) {
        this.content.items = [];
        return;
      }
      this.content.items.filter((item, i) => i != index);
    },
    // 设置监听
    // dom 元素本身  obj vue存储的对象  num 单次接触数  isContent 是否是内容面板
    setEventListener(dom, obj, num, isContent = false) {
      let objTouchstartFun;
      let objTouchmoveFun;
      let objTouchendFun;
      let touchObj;
      let index;
      let speedX;
      let speedY;
      let that = this;
      if (!isContent) {
        touchObj = this.touchData.items;
        index = obj.index;
        speedX = this.config.itemSpeedX;
        speedY = this.config.itemSpeedY;
        // index = 0; // 不给选多个 同时编辑了
      } else {
        touchObj = this.touchData.content;
        index = 0;
        speedX = this.config.speedX;
        speedY = this.config.speedY;
      }
      // 单指
      if (num == 1) {
        // 点击
        objTouchstartFun = function objTouchstartFun(event) {
          event.stopPropagation();
          const x = event.touches[0].clientX;
          const y = event.touches[0].clientY;
          if (!touchObj[index]) {
            touchObj[index] = initTouchObj;
          }
          touchObj[index].start.x = x;
          touchObj[index].start.y = y;
          // 添加 放大 缩小
          if (!isContent) {
            const diffX = x - (that.content.left + obj.left);
            const diffY = y - (that.content.top + obj.top);
            // 触摸 范围
            const scope = 10;
            if (typeof obj.size == "object") {
              // 左上
              if (diffX <= scope && diffY <= scope){
                console.log("左上");
                obj["isZoom"] = true;
                obj["zoomLeft"] = -1;
                obj["zoomTop"] = -1;
              }
              // 右上
              if (diffX >= obj.size.width - scope && diffY <= scope){
                console.log("右上");
                obj["isZoom"] = true;
                obj["zoomLeft"] = 1;
                obj["zoomTop"] = -1;
              }
              // 左下
              if (diffX <= scope && diffY >= obj.size.height - scope){
                console.log("左下");
                obj["isZoom"] = true;
                obj["zoomLeft"] = -1;
                obj["zoomTop"] = 1;
              }
              // 右下
              if (diffX >= obj.size.width - scope && diffY >= obj.size.height - scope){
                console.log("右下");
                obj["isZoom"] = true;
                obj["zoomLeft"] = 1;
                obj["zoomTop"] = 1;
              }
            }
          }
        };
        // 移动
        objTouchmoveFun = function objTouchmoveFun(event) {
          event.stopPropagation();
          const x = event.changedTouches[0].clientX;
          const y = event.changedTouches[0].clientY;
          const diffX = x - touchObj[index].start.x;
          const diffY = y - touchObj[index].start.y;
          // 放大 缩小
          if (!isContent) {
            // 图片
            if (typeof obj.size == "object" && obj["isZoom"]) {
              if (obj["zoomLeft"] == -1) obj.left += diffX * speedX;
              if (obj["zoomTop"] == -1) obj.top += diffY * speedY;
              obj.size.width += diffX * obj["zoomLeft"];
              obj.size.height += diffY * obj["zoomTop"];
            }
            // 文字
            else if (typeof obj.size == "number") {
            }
            else {
              obj.left += diffX * speedX;
              obj.top += diffY * speedY;
            }
          }
          else {
            obj.left += diffX * speedX;
            obj.top += diffY * speedY;
          }
          // 下一次开始
          touchObj[index].start.x = x;
          touchObj[index].start.y = y;
        };
        // 离开
        objTouchendFun = function objTouchendFun(event) {
          event.stopPropagation();
          if (!isContent) {
            obj["isZoom"] = false;
          }
        }

        dom.addEventListener("touchstart", objTouchstartFun);
        dom.addEventListener("touchmove", objTouchmoveFun);
        dom.addEventListener("touchend", objTouchendFun);
        obj.eventListenerFunsList ? "" : (obj.eventListenerFunsList = {});
        obj.eventListenerFunsList.touchstart = objTouchstartFun;
        obj.eventListenerFunsList.touchmove = objTouchmoveFun;
        obj.eventListenerFunsList.touchend = objTouchendFun;
      }

      // 双指
      // else if(num == 2) {
      // }
    },
    // 取消监听
    clearEventListener(dom, listeners) {
      listeners &&
        Object.keys(listeners).forEach((key) => {
          dom.removeEventListener(key, listeners[key]);
        });
    },
  },
};
</script>

<style lang="less" scoped>
@color: #ff6600;
@bgColor: #ebebeb;
@textColor: #666;

* {
  margin: 0;
  padding: 0;
}
// 不遮挡鼠标点击
.no-pointer {
  -webkit-pointer-events: none;
  -moz-pointer-events: none;
  -ms-pointer-events: none;
  -o-pointer-events: none;
  pointer-events: none;
}
.font-color-base {
  color: @color;
}
.font-color-gray {
  color: #666;
}
.page {
  overflow: hidden;
  max-width: 100vw;
  max-height: 100vh;
  position: relative;
  .show-view-btn {
    font-size: 14px;
    position: absolute;
    top: 20px;
    left: 50px;
    z-index: 10;
  }
  .view-box {
    position: absolute;
    display: block;
    z-index: 10;
    top: 4vh;
    right: 18vw;
    background-color: #fff;
    border: 12px solid rgb(184, 184, 184);
    .view {
      position: absolute;
      display: block;
      // z-index: 10;
      // top: 4vh;
      // right: 50vw;
      border: 1px solid rgb(136, 136, 136);
      background-color: @bgColor;
      span {
        color: @textColor;
        position: absolute;
        padding: 1px;
      }
    }
  }
  .content {
    position: absolute;
    display: block;
    background-color: @bgColor;
    z-index: 0;
    // overflow: hidden;
    span {
      color: @textColor;
      position: absolute;
      // padding: 3px;
      .content-item-number {
        position: absolute;
        top: -5px;
        left: calc(50% - 8px);
        border-radius: 50%;
        width: 15px;
        height: 15px;
        text-align: center;
        color: @color;
        // border: 1px solid @color;
        font-size: 14px;
        background-color: #fff;
        opacity: 0.8;
      }
      img {
        display: block;
      }
      // * {
      //   box-sizing: border-box;
      // }
    }
    .content-item-selected {
      // padding: 3px;
      border: 1px dashed @color;
    }
  }
  .left-list,
  .right-list {
    width: 70vw;
    height: 100vh;
    background-color: @bgColor;
    .left-list-box,
    .right-list-box {
      display: flex;
      flex-direction: column;
      align-items: center;
      box-sizing: border-box;
      width: 100%;
      height: 100%;
      padding: 20px;
      div {
        width: 100%;
        display: flex;
        align-items: center;
        color: @textColor;
      }
      .left-list-item,
      .right-list-item {
        width: 100%;
        text-align: center;
        display: block;
        padding: 8px 10px;
        margin-top: 8px;
        margin-left: 8px;
        background-color: #fff;
        color: @textColor;
      }
      .right-list-item-selected {
        background-color: @color;
        color: #fff;
      }
    }
  }
  .right-list {
    width: 50vw;
    height: 100vh;
    background-color: @bgColor;
  }
  .show-icon,
  .add-icon {
    position: absolute;
    top: 20px;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    border-width: 2px;
    border-style: solid;
    font-size: 14px;
    text-align: center;
    line-height: 13px;
    border-color: @color;
    color: @color;
    z-index: 20;
  }
  .show-icon {
    left: 20px;
  }
  .add-icon {
    right: 20px;
  }
}
</style>
